package com.sky.service.impl;

import com.sky.dto.OrderReportDTO;
import com.sky.dto.SalesReportDTO;
import com.sky.dto.TurnoverReportDTO;
import com.sky.dto.UserReportDTO;
import com.sky.entity.Orders;
import com.sky.mapper.OrdersMapper;
import com.sky.mapper.UserMapper;
import com.sky.service.ReportService;
import com.sky.vo.*;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ReportServiceImpl implements ReportService {

    @Autowired
    private OrdersMapper ordersMapper;

    @Autowired
    private UserMapper userMapper;

    @Override
    public TurnoverReportVO turnoverStatistics(LocalDate begin, LocalDate end) {
        //1. 获取日期列表
        List<String> dateList = getDateList(begin, end);

        //2. 统计指定日期范围的营业额列表 - SQL
        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);

        //2.1 查询数据库获取原始结果
        List<TurnoverReportDTO> turnoverReportDTOList = ordersMapper.selectTurnoverList(beginTime, endTime, Orders.ORDER_STAUTS_COMPLETED);

        //2.2 原始结果-->Map(key: 日期, value: 营业额)
        Map<String, BigDecimal> dataMap = turnoverReportDTOList.stream().collect(Collectors.toMap(TurnoverReportDTO::getOrderDate, TurnoverReportDTO::getOrderMoney));

        //2.3 遍历日期列表, 获取每一个日期对应的营业额, 如果没有营业额, 设置为0 ---> 集合
        List<BigDecimal> turnoverList = dateList.stream().map(date -> {
            return dataMap.get(date) == null ? new BigDecimal("0") : dataMap.get(date);
        }).collect(Collectors.toList());

        //3. 封装数据并返回
        return new TurnoverReportVO(dateList, turnoverList);
    }



    /**
     * 获取指定时间范围内的日期列表
     */
    private List<String> getDateList(LocalDate begin, LocalDate end) {
        List<LocalDate> localDateList = begin.datesUntil(end.plusDays(1)).collect(Collectors.toList());
        return localDateList.stream().map(localDate -> {
            return localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        }).collect(Collectors.toList());
    }


    @Override
    public UserReportVO userStatistics(LocalDate begin, LocalDate end) {
        //1. 获取日期列表
        List<String> dateList = getDateList(begin, end);

        //2. 获取指定时间范围内, 用户新增列表数据 - SQL .
        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);

        //2.1 查询原始数据
        List<UserReportDTO> userReportDTOList = userMapper.countAddByCreateTime(beginTime, endTime);

        //2.2 将原始数据 , 转为Map (key: 日期 , value: 新增用户数量)
        Map<String, Integer> dataMap = userReportDTOList.stream().collect(Collectors.toMap(UserReportDTO::getCreateDate, UserReportDTO::getUserCount));

        //2.3 遍历日期列表,  从map集合中获取数据, 如果没有, 就设置为 0
        List<Integer> newUserList = dateList.stream().map(date -> dataMap.get(date) == null ? 0 : dataMap.get(date)).collect(Collectors.toList());


        //3. 获取指定时间范围内, 用户总量列表数据 -- 2023-06-01 2023-06-10
        //3.1 查询开始时间之前, 一共多少个用户 - 基数 23  //TODO
        Integer baseCount = userMapper.countTotalByCreateTime(beginTime);

        //3.2 累加 ----> 集合
        List<Integer> totalUserList = new ArrayList<>();
        for (Integer add : newUserList) {
            baseCount += add;
            totalUserList.add(baseCount);
        }

        return new UserReportVO(dateList, totalUserList, newUserList);
    }


    @Override
    public OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {
        //1. 获取日期列表
        List<String> dateList = getDateList(begin, end);

        //2. 获取每日订单总数列表
        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);

        List<OrderReportDTO> orderReportDTOList = ordersMapper.countOrderByOrderTimeAndStatus(beginTime, endTime, null);
        Map<String, Integer> orderMap = orderReportDTOList.stream().collect(Collectors.toMap(OrderReportDTO::getOrderDate, OrderReportDTO::getOrderCount));

        List<Integer> orderCountList = dateList.stream().map(date -> orderMap.get(date) == null ? 0 : orderMap.get(date)).collect(Collectors.toList());

        //3. 获取每日有效订单总数列表
        List<OrderReportDTO> validOrderReportDTOList = ordersMapper.countOrderByOrderTimeAndStatus(beginTime, endTime, Orders.ORDER_STAUTS_COMPLETED);
        Map<String, Integer> validOrderMap = validOrderReportDTOList.stream().collect(Collectors.toMap(OrderReportDTO::getOrderDate, OrderReportDTO::getOrderCount));

        List<Integer> validOrderCountList = dateList.stream().map(date -> validOrderMap.get(date) == null ? 0 : validOrderMap.get(date)).collect(Collectors.toList());

        //4. 订单总数 -- orderCountList中的数据累加
        Integer totalOrderCount = orderCountList.stream().reduce(Integer::sum).get();

        //5. 有效订单数量 -- validOrderCountList中的数据累加
        Integer validOrderCount = validOrderCountList.stream().reduce(Integer::sum).get();

        //6. 订单完成率
        Double orderCompletionRate = validOrderCount.doubleValue() / totalOrderCount;

        return new OrderReportVO(dateList, orderCountList, validOrderCountList, totalOrderCount, validOrderCount, orderCompletionRate);
    }



    @Override
    public SalesTop10ReportVO salesTop10(LocalDate begin, LocalDate end) {
        //1. 查询指定时间区间内的TOP10菜品
        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);
        List<SalesReportDTO> salesReportDTOList = ordersMapper.getSalesTop10(beginTime, endTime); //goodsName     goodsNumber


        //2. 解析结果数据
        List<String> nameList = salesReportDTOList.stream().map(salesReportDTO -> {
            return salesReportDTO.getGoodsName();
        }).collect(Collectors.toList());

        List<Integer> numberList = salesReportDTOList.stream().map(salesReportDTO -> {
            return salesReportDTO.getGoodsNumber();
        }).collect(Collectors.toList());

        return new SalesTop10ReportVO(nameList, numberList);
    }


    @Autowired
    private HttpServletResponse response;

    @Override
    public void exportData() throws Exception {
        //1. 获取近一个月的时间 - 开始 , 结束
        LocalDate begin = LocalDate.now().minusDays(30);
        LocalDate end = LocalDate.now().minusDays(1);

        //2. 调用Mapper接口查询数据中的原始数据  -- 数据概览
        BusinessDataVO businessDataVO = ordersMapper.countByTime(LocalDateTime.of(begin, LocalTime.MIN), LocalDateTime.of(end, LocalTime.MAX));
        Integer newUserCount = userMapper.countByTime(LocalDateTime.of(begin, LocalTime.MIN), LocalDateTime.of(end, LocalTime.MAX));

        String rangeDate = "时间范围: " + begin.toString() + " 到 " + end.toString() ;

        //4. 加载报表Excel模板文件
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("templates/运营数据报表模板.xlsx");
        Workbook workbook = new XSSFWorkbook(inputStream);
        Sheet sheet = workbook.getSheetAt(0);

        //5. 定位单元格 , 填充数据 -- 数据概览
        sheet.getRow(1).getCell(1).setCellValue(rangeDate); //时间
        sheet.getRow(3).getCell(2).setCellValue(businessDataVO.getTurnover());//营业额
        sheet.getRow(3).getCell(4).setCellValue(businessDataVO.getOrderCompletionRate()); //订单完成率
        sheet.getRow(3).getCell(6).setCellValue(newUserCount); //新增用户数
        sheet.getRow(4).getCell(2).setCellValue(businessDataVO.getValidOrderCount()); //有效订单
        sheet.getRow(4).getCell(4).setCellValue(businessDataVO.getUnitPrice()); //平均客单价

        //6. 调用Mapper接口查询数据中的原始数据  - 每一天的明细
        for (int i = 0; i < 30; i++) {
            //获取时间
            LocalDate everyDate = begin.plusDays(i);

            //6.1 查询每一天的运营信息
            BusinessDataVO _businessDataVO = ordersMapper.countByTime(LocalDateTime.of(everyDate, LocalTime.MIN), LocalDateTime.of(everyDate, LocalTime.MAX));
            Integer _newUserCount = userMapper.countByTime(LocalDateTime.of(everyDate, LocalTime.MIN), LocalDateTime.of(everyDate, LocalTime.MAX));

            //6.2 填充数据
            Row row = sheet.getRow(7 + i);
            row.getCell(1).setCellValue(everyDate.toString()); //时间
            row.getCell(2).setCellValue(_businessDataVO.getTurnover()); //营业额
            row.getCell(3).setCellValue(_businessDataVO.getValidOrderCount()); //有效订单
            row.getCell(4).setCellValue(_businessDataVO.getOrderCompletionRate()); //订单完成率
            row.getCell(5).setCellValue(_businessDataVO.getUnitPrice()); //平均客单价
            row.getCell(6).setCellValue(_newUserCount); //新增用户数
        }

        //7. 下载文件 - 流
        ServletOutputStream out = response.getOutputStream();
        workbook.write(out); //将Excel文件作为流, 响应给浏览器 , 自动下载

        //8. 释放资源
        out.close();
        workbook.close();
    }
}
